﻿using CPF;
using CPF.Animation;
using CPF.Charts;
using CPF.Controls;
using CPF.Drawing;
using CPF.Shapes;
using CPF.Styling;
using CPF.Svg;
using CPF.Threading;
using SkiaSharp;
using System;

namespace CPFUI.IControl.Process
{
    [CPF.Design.DesignerLoadStyle("res://$safeprojectname$/Stylesheet1.css")]//用于设计的时候加载样式
    public class CircularProgress : Control
    {
        #region 常量

        private const int DEFAULT_INTERVAL = 60;
        private readonly Color DEFAULT_TICK_COLOR = Color.FromArgb(255,58, 58, 58);
        private const int DEFAULT_TICK_WIDTH = 2;
        private const int MINIMUM_INNER_RADIUS = 4;
        private const int MINIMUM_OUTER_RADIUS = 8;
        private Size MINIMUM_CONTROL_SIZE = new Size(28, 28);
        private const int MINIMUM_PEN_WIDTH = 2;

        #endregion
        

        #region 变量

        private int m_Interval;
        Point m_CentrePt = new Point();
        int m_InnerRadius = 0;
        int m_OuterRadius = 0;
        int m_StartAngle = 0;
        byte m_AlphaStartValue = 0;
        int m_SpokesCount = 0;
        int m_AngleIncrement = 0;
        byte m_AlphaDecrement = 0;
        DispatcherTimer m_Timer = null;

        #endregion

        #region 属性

        /// <summary>
        /// 每个刻度的时间间隔
        /// </summary>
        public int Interval
        {
            get
            {
                return m_Interval;
            }
            set
            {
                if (value > 0)
                {
                    m_Interval = value;
                }
                else
                {
                    m_Interval = DEFAULT_INTERVAL;
                }
            }
        }

        /// <summary>
        /// 块颜色
        /// </summary>
        public CPF.Drawing.Color TickColor { get; set; }

        /// <summary>
        /// 旋转方向-顺时针/逆时针
        /// </summary>
        public Direction Rotation { get; set; }

        public bool IsChangeSize { get; set; }
        /// <summary>
        /// 旋转方向-顺时针/逆时针
        /// </summary>
        public GraphType GraphType { get; set; }
        /// <summary>
        /// 刻度开始的角度
        /// </summary>
        public int StartAngle
        {
            get
            {
                return m_StartAngle;
            }
            set
            {
                m_StartAngle = value;
            }
        }

        #endregion

        public CircularProgress()
        {
            this.TickColor = DEFAULT_TICK_COLOR;
            this.Interval = DEFAULT_INTERVAL;
            // Default rotation direction is clockwise
            this.Rotation = Direction.Clockwise;
            GraphType = GraphType.Line;
            IsChangeSize = false;
            // Default starting angle is 12 o'clock
            this.StartAngle = 270;
            // Default number of Spokes in this control is 12
            m_SpokesCount = 12;
            // Default alpha value of the first spoke is 255
            m_AlphaStartValue = 255;
            // Calculate the angle between adjacent spokes
            m_AngleIncrement = (int)(360 / m_SpokesCount);
            // Calculate the change in alpha between adjacent spokes
            m_AlphaDecrement = (byte)((m_AlphaStartValue - 15) / m_SpokesCount);

            
            
        }
        //模板定义
        protected override void InitializeComponent()
        {
            IsAntiAlias = true;
            this.MinWidth = MINIMUM_CONTROL_SIZE.Width;
            this.MinHeight = MINIMUM_CONTROL_SIZE.Height;
            
        }


        #region 方法

        /// <summary>
        /// 将度数转换为弧度
        /// </summary>
        /// <param name="degrees">Degrees</param>
        /// <returns></returns>
        private double ConvertDegreesToRadians(int degrees)
        {
            return ((Math.PI / (double)180) * degrees);
        }

        #endregion

        #region 启动停止方法

        /// <summary>
        /// 开始旋转
        /// </summary>
        public void Start()
        {
            if (m_Timer != null)
            {
                m_Timer.Interval = TimeSpan.FromMilliseconds(Interval);
                m_Timer.IsEnabled = true;
                m_Timer.Start();
            }
        }

        /// <summary>
        /// 停止旋转
        /// </summary>
        public void Stop()
        {
            if (m_Timer != null)
            {
                m_Timer.IsEnabled = false;
                m_Timer.Stop();
            }
        }

        #endregion
#if !DesignMode //用户代码写到这里，设计器下不执行，防止设计器出错
        protected override void OnInitialized()
        {
            base.OnInitialized();
            m_Timer = new DispatcherTimer();
            m_Timer.Interval = TimeSpan.FromMilliseconds(Interval);
            m_Timer.Tick += M_Timer_Tick;
            m_Timer.IsEnabled = false;
            m_Timer.Start();
        }

        private void M_Timer_Tick(object sender, EventArgs e)
        {
            if (Rotation == Direction.Clockwise)
            {
                m_StartAngle += m_AngleIncrement;

                if (m_StartAngle >= 360)
                    m_StartAngle = 0;
            }
            else if (Rotation == Direction.Anticlockwise)
            {
                m_StartAngle -= m_AngleIncrement;

                if (m_StartAngle <= -360)
                    m_StartAngle = 0;
            }

            Invalidate();
        }

        protected override void OnRender(DrawingContext dc)
        {

            base.OnRender(dc);
            byte alpha = m_AlphaStartValue;
            int angle = m_StartAngle;
            // Calculate the location around which the spokes will be drawn
            float width = this.ActualSize.Width < this.ActualSize.Height ? this.ActualSize.Width : this.ActualSize.Height;
            m_CentrePt = new Point(width / 2, this.ActualSize.Height / 2);
            // Calculate the width of the pen which will be used to draw the spokes
            float penwidth = (int)(width / 15);
            if (penwidth < MINIMUM_PEN_WIDTH)
                penwidth = MINIMUM_PEN_WIDTH;
            // Calculate the inner and outer radii of the control. The radii should not be less than the
            // Minimum values
            m_InnerRadius = (int)(width * (140 / (float)800));
            if (m_InnerRadius < MINIMUM_INNER_RADIUS)
                m_InnerRadius = MINIMUM_INNER_RADIUS;
            m_OuterRadius = (int)(width * (250 / (float)800));
            if (m_OuterRadius < MINIMUM_OUTER_RADIUS)
                m_OuterRadius = MINIMUM_OUTER_RADIUS;
            // Render the spokes
            

                for (int i = 0; i < m_SpokesCount; i++)
                {
                using (Brush pen = new SolidColorBrush(Color.FromArgb(alpha, TickColor.R, TickColor.G, TickColor.B)))
                {
                    float v = alpha*1.0f/255.0f;
                    Point pt1 = new Point(m_InnerRadius * (float)Math.Cos(ConvertDegreesToRadians(angle)), m_InnerRadius * (float)Math.Sin(ConvertDegreesToRadians(angle)));
                    Point pt2 = new Point(m_OuterRadius * (float)Math.Cos(ConvertDegreesToRadians(angle)), m_OuterRadius * (float)Math.Sin(ConvertDegreesToRadians(angle)));

                    pt1.X += m_CentrePt.X;
                    pt1.Y += m_CentrePt.Y;
                    pt2.X += m_CentrePt.X;
                    pt2.Y += m_CentrePt.Y;
                    //m_Pen.Color = Color.FromArgb(alpha, this.TickColor);
                    if(GraphType== GraphType.Line)
                    {
                        dc.DrawLine(new Stroke(penwidth) { StrokeCap = CapStyles.Round }, pen, pt1, pt2);
                    }
                    else
                    {
                        if (IsChangeSize)
                        {
                            dc.FillEllipse(pen, pt2, penwidth / m_SpokesCount + (penwidth) *v, penwidth / m_SpokesCount + (penwidth) * v);
                        }
                        else
                        {
                            dc.FillEllipse(pen, pt2, penwidth , penwidth );
                        }
                    }
                    //e.Graphics.DrawLine(m_Pen, pt1, pt2);

                    if (Rotation == Direction.Clockwise)
                    {
                        angle -= m_AngleIncrement;
                    }
                    else if (Rotation == Direction.Anticlockwise)
                    {
                        angle += m_AngleIncrement;
                    }

                    //if (i < 5)
                    //    alpha -= 45;
                    alpha -= m_AlphaDecrement;
                }
            }
        }
        //用户代码

#endif
    }

    #region 枚举
    /// <summary>
    /// 旋转方向
    /// </summary>
    public enum Direction
    {
        /// <summary>
        /// 顺时针
        /// </summary>
        Clockwise,
        /// <summary>
        /// 逆时针
        /// </summary>
        Anticlockwise
    }

    /// <summary>
    /// 旋转方向
    /// </summary>
    public enum GraphType
    {
        /// <summary>
        /// 线
        /// </summary>
        Line,
        /// <summary>
        /// 圆
        /// </summary>
        Ellipse
    }
    #endregion
}
